#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <signal.h>

#include <net/if.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include "cJSON/cJSON.h"

// API
char buf1_city[200] = {0};
char buf2[200] = {0};
char buf3[200] = {0};
char buf4[200] = {0};

// 读取一行（以 \r\n 结尾）
char *read_line(int sockfd) {
    char *line = calloc(1, 1024);
    int n = 0;
    while (1) {
        read(sockfd, line + n, 1);
        n++;
        if (n >= 2 && line[n - 2] == '\r' && line[n - 1] == '\n') {
            line[n - 2] = '\0'; // 去掉 \r\n
            break;
        }
    }
    return line;
}

// 读取分块传输编码的响应体
char *read_chunked_body(int sockfd) {
    char *body = calloc(1, 4096);
    int body_length = 0;

    while (1) {
        // 读取块大小
        char *chunk_size_line = read_line(sockfd);
        int chunk_size = strtol(chunk_size_line, NULL, 16); // 十六进制转整数
        free(chunk_size_line);

        if (chunk_size == 0) {
            // 读取最后一个块的 \r\n
            read_line(sockfd);
            break;
        }

        // 读取块数据
        char *chunk_data = calloc(1, chunk_size + 2); // 额外空间用于 \r\n
        read(sockfd, chunk_data, chunk_size);
        chunk_data[chunk_size] = '\0';

        // 将块数据追加到 body
        memcpy(body + body_length, chunk_data, chunk_size);
        body_length += chunk_size;

        // 读取块数据后的 \r\n
        read_line(sockfd);
        free(chunk_data);
    }

    return body;
}

int main(int argc, char const *argv[])
{
    // 获取指定服务器 IP
    struct hostent *p;
    p = gethostbyname("getweather.market.alicloudapi.com");
    if (p == NULL) {
        printf("无法解析服务器地址\n");
        return 1;
    }

    // 创建 TCP 连接
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        printf("创建套接字失败\n");
        return 1;
    }

    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    bzero(&addr, len);
    addr.sin_family = AF_INET;
    addr.sin_addr = *(struct in_addr *)((p->h_addr_list)[0]);
    addr.sin_port = htons(80);

    if (connect(sockfd, (struct sockaddr *)&addr, len) != 0) {
        printf("连接失败\n");
        return 1;
    }

    // 发送 HTTP 请求
    char *http_request();
    char *s = http_request();
    write(sockfd, s, strlen(s));

    // 接收 HTTP 响应头部
    char *http_response = calloc(1, 1024);
    if (http_response == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    int n = 0;
    while (1) {
        read(sockfd, http_response + n, 1);
        n++;

        if (strstr(http_response, "\r\n\r\n") || (n >= 1024)) {
            break;
        }
    }
    // printf("HTTP响应头部:\n%s", http_response);

    // 读取分块传输编码的响应体
    char *json = read_chunked_body(sockfd);
    // printf("HTTP响应报体:(JSON)[%lu字节]\n%s\n", strlen(json), json);

    // 解析 cJSON
    cJSON *root = cJSON_Parse(json);
    if (root == NULL) {
        printf("JSON 解析失败: %s\n", cJSON_GetErrorPtr());
        return 1;
    }

    // 获取 data 对象
    cJSON *data = cJSON_GetObjectItem(root, "data");
    if (data == NULL) {
        printf("data 解析失败\n");
        cJSON_Delete(root);
        return 1;
    }

    // 解析城市信息
    cJSON *cityInfo = cJSON_GetObjectItem(data, "cityInfo");
    if (cityInfo != NULL) {
        sprintf(buf1_city, "%s %s %s 城市ID:%s\n",
                cJSON_GetObjectItem(cityInfo, "areaCn")->valuestring,
                cJSON_GetObjectItem(cityInfo, "cityCn")->valuestring,
                cJSON_GetObjectItem(cityInfo, "provCn")->valuestring,
                cJSON_GetObjectItem(cityInfo, "areaId")->valuestring);
        printf("%s", buf1_city);
    }

    // 解析白天天气信息
    cJSON *day = cJSON_GetObjectItem(data, "day");
    if (day != NULL) {
        sprintf(buf2, "%s %s 温度:%s 风力:%s %s\n",
                cJSON_GetObjectItem(day, "sunUp")->valuestring,
                cJSON_GetObjectItem(day, "weather")->valuestring,
                cJSON_GetObjectItem(day, "temperature")->valuestring,
                cJSON_GetObjectItem(day, "wind")->valuestring,
                cJSON_GetObjectItem(day, "wind_pow")->valuestring);
        printf("%s", buf2);
    }

    // 解析夜间天气信息
    cJSON *night = cJSON_GetObjectItem(data, "night");
    if (night != NULL) {
        sprintf(buf3, "%s %s 温度:%s 风力:%s %s\n",
                cJSON_GetObjectItem(night, "sunDown")->valuestring,
                cJSON_GetObjectItem(night, "weather")->valuestring,
                cJSON_GetObjectItem(night, "temperature")->valuestring,
                cJSON_GetObjectItem(night, "wind")->valuestring,
                cJSON_GetObjectItem(night, "wind_pow")->valuestring);
        printf("%s", buf3);
    }

    // 解析当前天气信息
    cJSON *now = cJSON_GetObjectItem(data, "now");
    if (now != NULL) {
        sprintf(buf4, "当前:%s 温度:%s°C 湿度:%s 风力: %s %s 空气质量: %s\n",
                cJSON_GetObjectItem(now, "weather")->valuestring,
                cJSON_GetObjectItem(now, "temp")->valuestring,
                cJSON_GetObjectItem(now, "SD")->valuestring,
                cJSON_GetObjectItem(now, "WD")->valuestring,
                cJSON_GetObjectItem(now, "WS")->valuestring,
                cJSON_GetObjectItem(now, "aqi")->valuestring);
        printf("%s", buf4);
    }

    // 释放 cJSON 对象
    cJSON_Delete(root);

    // 释放动态分配的内存
    free(http_response);
    free(json);

    return 0;
}

char *http_request() {
    // 查天气（广州）
    char *requestHead = "GET /lundear/weather1d?areaCode=440114&areaCn=areaCn&ip=ip&lng=lng&lat=lat&needalarm=needalarm&need1hour=need1hour&need3hour=need3hour&needIndex=needIndex&needObserve=needObserve HTTP/1.1\r\n"
                        "Host: getweather.market.alicloudapi.com\r\n"
                        "Authorization: APPCODE a83865167d05434f92a60aa5edb9498d\r\n"
                        "Connection: close\r\n\r\n";

    return requestHead;
}






















// #include <stdio.h>
// #include <errno.h>
// #include <fcntl.h>
// #include <unistd.h>
// #include <string.h>
// #include <stdlib.h>
// #include <strings.h>
// #include <signal.h>

// #include <net/if.h>
// #include <arpa/inet.h>
// #include <sys/ioctl.h>
// #include <sys/socket.h>
// #include <netinet/in.h>
// #include <netdb.h>

// #include "cJSON/cJSON.h"

// //API
// char buf1_city[100]={0};
// char buf2[100]={0};
// char buf3[100]={0};

// int main(int argc, char const *argv[])
// {
//     //获取指定服务器IP
//     struct hostent *p;
//     // p = gethostbyname("iweather.market.alicloudapi.com");
//     p = gethostbyname("getweather.market.alicloudapi.com");
//     // printf("服务器IP:%s\n", 
//     //         inet_ntoa(*(struct in_addr*)((p->h_addr_list)[0])));

//     //创建TCP连接
//     int sockfd = socket(AF_INET, SOCK_STREAM, 0);
//     struct sockaddr_in addr;
//     socklen_t len = sizeof(addr);
//     bzero(&addr, len);
//     addr.sin_family = AF_INET;
//     addr.sin_addr = *(struct in_addr*)((p->h_addr_list)[0]);
//     addr.sin_port = htons(80);
//     if(connect(sockfd, (struct sockaddr *)&addr, len) != 0)
//         printf("连接失败\n");

//     //按服务器规定发送请求报文
//     char *http_request();
//     char *s = http_request();
//     write(sockfd, s, strlen(s));

//     //接收、解析HTTP响应头部
//     char *http_response = calloc(1, 1024);
//     int n = 0;
//     while(1)
//     {
//         read(sockfd, http_response + n, 1);
//         n++;

//         if(strstr(http_response, "\r\n\r\n") || (n >= 1024))
//             break;
//     }
//     printf("HTTP响应头部:\n%s",http_response);

//     char *json = calloc(1, 2048);  
//     int nread = read(sockfd, json, 2048);
//     printf("HTTP响应报体:(JSON)[%d字节]\n%s\n", nread, json);

//     // char *pp = strtok(strchr(json, '\n')+1, "\r\n"); 
//     // 解析cJSON
//     cJSON *root = cJSON_Parse(json);
//     if(root == NULL)
//         printf("json 解析失败\n");
  
//     cJSON *data = cJSON_GetObjectItem(root, "data");//尝试从root对象中获取名为"data"的项，并将其存储在Traces变量中
//     if(data == NULL)
//         printf("data 解析失败\n");


//     // // 解析城市信息
//     // cJSON *cityinfo = cJSON_GetObjectItem(data, "cityinfo");
//     // if (cityinfo != NULL) {
//     //     sprintf(buf1_city,"城市信息:省份: %s 城市: %s 地区: %s 邮编: %s\n",
//     //                                                         cJSON_GetObjectItem(cityinfo, "provinces")->valuestring,
//     //                                                         cJSON_GetObjectItem(cityinfo, "city")->valuestring,
//     //                                                         cJSON_GetObjectItem(cityinfo, "area")->valuestring,
//     //                                                         cJSON_GetObjectItem(cityinfo, "yb")->valuestring);
//     //     // printf("%s",buf1_city);
//     // }

//     // // 解析当前天气信息
//     // cJSON *now = cJSON_GetObjectItem(data, "now");
//     // if (now != NULL) {
//     //     // printf("当前天气:\n");
//     //     cJSON *city = cJSON_GetObjectItem(now, "city");
//     //     if (city != NULL) {
//     //         sprintf(buf2,"当前天气:天气:%s 天气编号: %s 夜间温度: %s°C 日间温度: %s°C\n",
//     //                                                         cJSON_GetObjectItem(city, "weather")->valuestring,
//     //                                                         cJSON_GetObjectItem(city, "weather_code")->valuestring,
//     //                                                         cJSON_GetObjectItem(city, "night_air_temperature")->valuestring,
//     //                                                         cJSON_GetObjectItem(city, "day_air_temperature")->valuestring);
//     //         // printf("%s",buf2);
//     //     }

//     //     cJSON *detail = cJSON_GetObjectItem(now, "detail");
//     //     if (detail != NULL) {
//     //         sprintf(buf3,"时间: %s %s 星期: %s 温度: %s°C 湿度: %s 空气质量: %s\n",
//     //                                                         cJSON_GetObjectItem(detail, "date")->valuestring,
//     //                                                         cJSON_GetObjectItem(detail, "time")->valuestring,
//     //                                                         cJSON_GetObjectItem(detail, "week")->valuestring,
//     //                                                         cJSON_GetObjectItem(detail, "temperature")->valuestring,
//     //                                                         cJSON_GetObjectItem(detail, "humidity")->valuestring,
//     //                                                         cJSON_GetObjectItem(detail, "quality")->valuestring);
//     //         // printf("%s",buf3);
//     //     }
//     // }

//     // printf("%s",buf1_city);
//     // printf("%s",buf2);
//     // printf("%s",buf3);

//     // 释放 cJSON 对象
//     cJSON_Delete(root);

//     return 0;
// }

// // char *http_request()
// // {
// //     //查天气
// //     char *requestHead = "GET /scenic?jq=%E8%8A%B1%E9%83%BD&city=%e5%b9%bf%e5%b7%9e&needday=1 HTTP/1.1\r\n"
// //                         "Host: iweather.market.alicloudapi.com\r\n"
// //                         "Authorization: AppCode a83865167d05434f92a60aa5edb9498d\r\n\r\n";

// //     return requestHead;
// // }

// char *http_request() {
//     // 查天气（广州）
//     char *requestHead = "GET /lundear/weather1d?areaCode=440114&areaCn=areaCn&ip=ip&lng=lng&lat=lat&needalarm=needalarm&need1hour=need1hour&need3hour=need3hour&needIndex=needIndex&needObserve=needObserve HTTP/1.1\r\n"
//                         "Host: getweather.market.alicloudapi.com\r\n"
//                         "Authorization: APPCODE a83865167d05434f92a60aa5edb9498d\r\n"
//                         "Connection: close\r\n\r\n";

//     return requestHead;
// }
